import demo1.Dog;

import java.util.*;

public class Test {
    public static void main(String[] args) {
        //关于静态内部类的问题：
        Dog.Inner inner = new Dog.Inner();//将其设置为不是一个包中，
        //静态内部类的访问修饰限定符默认为Default ,所有不能够在不同包中进行访问。
        Integer i = 2;
        Integer i2 = 3;
        System.out.println(i.compareTo(i2));







    }





    public static void main1(String[] args) {
         //5道关于hashtong的oj题：
        //题目1 ：只出现一次的数字
        //题目2： 复制带随机指针的链表
        //题目3：宝石与石头
       //求字符串的长度的方法
       //题目4：坏键盘打字
       //关于scanner类的使用
     //   Scanner scanner = new Scanner();


    }
    //题目1：
    public int singleNumber(int[] nums) {
        //1.  只出现一次的数字
        //先将遍历数组中的元素放入集合中，然后在遇到相同的元素时，再将集合中的元素进行取出。
        Set<Integer> set =  new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            //此时直接调用集合中的方法即可
            //  int index = nums[k]%
            //问题：  哈希桶中没有获取key的值的方法吗？
            //先判断当前的数字是否在哈希桶中,HashSet的底层也是Hashmap
            if(set.contains(nums[i])){
                //如果存在
                set.remove(nums[i]);
            }else{
                //如果不存在
                set.add(nums[i]);
            }
        }
        //最后返回set集合中剩余的元素
        for (int i = 0; i < nums.length; i++) {
            if(set.contains(nums[i])) {
                return  nums[i];
            }
        }
     return -1;
    }
 //题目2:









     /* public Node copyRandomList(Node head) {
               //

      }*/
    //题目4：旧键盘
public void oldKeyBorad1(String str1,String str2){
           //将str1的全部字母大写
        String newstr1 =  str1.toUpperCase();   //将所有的小写字母都转为大写
        //将输入的字母保存到集合当中去
      Set<Character> set = new HashSet<>();
    for (int i = 0; i < str1.length(); i++) {
        //此时字符串中的数字也是字符，也有对应的ASCII编码
        char ch =  str1.charAt(i);
        if(!set.contains(ch)){
            //如果集合中没有当前的字符
            set.add(ch);
        }
    }
  //然后再遍历输出的字符串，将在集合中遇到的输出的字符串全部删除
    for (int i = 0; i < str2.length(); i++) {
        char ch =  str2.charAt(i);
        if(set.contains(ch)){
            set.remove(ch);
        }
    }
   //然后再将集合中的字符打印出来。这个方法有些麻烦。
}
    public void oldKeyBorad2(String str1,String str2){
       //先将输出的字符串存入到集合中，然后再将输入的字符串存入到另一个集合中，存入的同时，打印它，也达到了去重的目的
    }

    //题目 5 ：
    public List<String> topKFrequent(String[] words, int k) {
        HashMap<String,Integer> map = new HashMap<>();
        //遍历单词列表
        for(int i=0 ;i<words.length;i++){
            //如果集合中已经存在这个单词
            if(map.containsKey(words[i])){
                int value = map.get(words[i]);
                //然后将value的值加1
                map.replace(words[i],value+1);
            }else{
                //如果集合中不存在这个单词
                map.put(words[i],1);
            }
        }
    //在将所有的单词输入到集合中去后，开始进行排序,
          //要比较出前k个大的数据，可创建大小为k个数据的；根堆，遍历非小根堆的元素，遇到大于最小根的数据，则进行交换，
        // 然后再调整堆为小根堆，再循环上述步骤。
         // 先创建一个小根堆
        PriorityQueue<Map.Entry<String,Integer>> minHeap = new PriorityQueue<>(
                //在小根堆中，对于自定义类型，需要传入相应的比较器
                //比较器是怎么回事？
                new Comparator<Map.Entry<String, Integer>>() {
                    @Override
                    public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                          //需要比较两个对象的value值，如果两个对象的value值相同，还需要比较key值
                          if(o1.getValue().compareTo(o2.getValue())==0){
                              //o1.getValue方法获取的int类型的值，为什么可以调用comoareTo方法？
                              //
                              return o2.getKey().compareTo(o1.getKey());
                          }
                        return o1.getValue().compareTo(o2.getValue());
                          //String类与Integer类中重写的compareTo方法返回什么？常数

                          //getValue之所以可以调用compareto方法，根本上是因为返回值类型是Integer类型，泛型传输时传输的即为Integer类型

                    }
                }
        );   //要比较出现次数最多的单词
        //并不是所有的泛型都可以传输键值对，
        //循环遍历k个值
        //在创建好小根堆后，如何从集合中拿出k个键值对存入到小根堆中?
        //需要先获取集合变量，然后通过foreach遍历map内部的集合中，来获取键值对,用entrySet()方法获取
           //对于foreach语句如何使用？冒号: 前面为临时变量，冒号后面为要遍历的集合(数组等)。
        for (Map.Entry<String,Integer> entry: map.entrySet()) {
                  if(minHeap.size()<k){
                       minHeap.offer(entry);
                  }else{
                      //在将k个键值对放入小根堆后，
                     //默认创建的堆为小根堆，可以直接测试一下
                   //然后将集合中剩余的元素与堆顶元素进行比较
                      if(entry.getValue().compareTo(minHeap.peek().getValue()) >0){
                               //如果集合中剩余的元素比堆顶元素大，则进行交换，并且重新进行调整堆为小根堆
                          minHeap.poll();
                          minHeap.offer(entry);
                         //问题，在调整了堆顶元素后，不应该再执行调用方法吗？
                         //在方法内部已经自动调用了
                      }else if(entry.getValue().compareTo(minHeap.peek().getValue())==0 ){
                             //则按字母排列，判断两个键值对谁前前后
                            if(entry.getKey().compareTo(minHeap.peek().getKey())<0){
                                minHeap.poll();
                                minHeap.offer(entry);
                            }
                      }

                  }
        }
        //在将前k个出现次数最多的单词存入小根堆之后，再将小根堆中的数据存入数组顺序表中
        ArrayList <String>  list= new ArrayList<>();

        for (int i = 0; i < k; i++) {
            //遍历小根堆中的数据
            Map.Entry<String,Integer> tmp = minHeap.poll();
            list.add(tmp.getKey());

            //如何创建静态内部类对象？
            //Map.Entry<String,Integer> my = new Map.Entry<>();
         //  HashMap<String,Integer>.Node<String,Integer> node =  //明明是静态内部类，为什么不能访问实现呢？
        //    priorityQueue.offer();   //如何传入键值对？关于键值对的类封装在map类中
        }
     //   priorityQueue.offer()
        Collections.reverse(list);
        return list;

       }


















}
